﻿#include"stdafx.h"
#ifdef LK_FUNCTIONAL_FUNOBJ_
namespace LK
{
	namespace Functional
	{
		PObject IFunObjs::Call(PObject const&obj, Collection::PArray<PObject>const&Arguments)const
		{
			Collection::PArray<PType> arr = GetArgsType();//返回值和参数类型
			if ((Arguments.IsNull() ? 0 : Arguments.size()) != arr.size() - 2)
				throw PFunctionalException(L"函数调用时传入的参数数量不对,应传入" + PString(arr.size() - 2) + L"个参数，但却传入了" + PString(Arguments.IsNull() ? 0 : Arguments.size()) + L"个");
			PMObjects xr;//存放返回值的封箱
			if (!arr[0].IsPureType() || !arr[0].IsDerivedFrom(PType::Make<PObject>()))
				xr = PMObjects::MakeMObjectByTypeInfo(arr[0]);
			Collection::PArray<void*>args;//参数指针数组
			Collection::PArray<PObject> xcvrt;//参数封箱数组
			if (!Arguments.IsNull())//检测参数是否需要转换
			{
				args = new LK::Collection::DefaultArray<void*>(Arguments.GetLength());//参数指针
				xcvrt = new LK::Collection::DefaultArray<PObject>(Arguments.GetLength());//参数列表
				for (index_t i = 0; i < Arguments.GetLength(); ++i)//执行必要的类型转换过程，目标是填完args数组
				{
					PType& dt = arr[i + 2];//目标类型
					PType st;
					if (Arguments[i].IsNull())
					{
						if (!dt.IsPureTypeIgnoreExtents() || dt.IsReference() || !dt.IsDerivedFrom(PType::Make<PObject>()))
							throw PFunctionalException(L"传入的第" + PString(i + 1) + L"个参数为空");
					}
					else st = Arguments[i].GetType() == PType::Make<PMObjects>() ? ((PMObjects&)Arguments[i]).GetInnerType() : Arguments[i].GetType();
					if (st.IsNull())
						args[i] = (void*)&Arguments[i];
					else
					{
						if (dt != st)//需要转换
							xcvrt[i] = dt.DynamicConvertFrom(Arguments[i]);
						else xcvrt[i] = Arguments[i];
						args[i] = xcvrt[i].GetType() == PType::Make<PMObjects>() ? (void*)((PMObjects&)xcvrt[i]).GetDataPtr() : (void*)&xcvrt[i];
						if (dt.IsReference() || dt.IsArray() || dt.IsFunction())args[i] = *(void**)args[i];//需要从封箱数据指针转换到对象指针
					}
				}
			}
			void*pClass = obj.IsNull() ? NULL : obj.GetPtr()->GetObjectPtr();
			if (!pClass)
			{
				GetInnerPtr(&pClass);
				if (!pClass)pClass = (void*)&obj;
			}
			if (xr.IsNull())Call(&xr, pClass, args.IsNull() ? (void**)NULL : (void**)args);
			else Call(xr.GetDataPtr(), pClass, args.IsNull() ? (void**)NULL : (void**)args);
			return xr;
		}
		void PFunObjs::AddTypeInfo()
		{
#ifdef LK_REFLECTION_
			//引用反射命名空间
			using namespace Reflection;
			//获取类库的引用
			PTypeLibrary lib = GetGlobleLibrary();
			//获取类库中的全局命名空间
			PNamespaceNode globle = lib.GetGlobleNamespaceRef();
			//添加LK命名空间
			PNamespaceNode space = globle.FindOrAddNamespace(L"LK");
			//在LK命名空间中添加PException类型
			PTypeNode n = space.FindOrAddTypeNode(L"PFunObjs", PType::Make<PFunObjs>());
			//在PFunObj类型节点中添加成员函数
			n.AddFunction(L"GetClassTypeInfo", &PFunObjs::GetClassTypeInfo);
			n.AddFunction(L"Call", (PObject(PFunObjs::*)(PObject const&, Collection::PArray<PObject>const&)const)&PFunObjs::Call);
			n.AddFunction(L"GetArgsType", &PFunObjs::GetArgsType);
			//设置继承
			n.AddBaseType(PType::Make<PObject>());
#endif
		}
	}
}
#endif
